<?php
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

if (!class_exists('Context')) {

	/**
	 * Context object. Holds information about the current
	 * context (user,session, request)
	 * @author Alecsandru Gabriel DINU
	 * @since Jun 11, 2008
	 */
	class Context {
		private $user;
		private $request;
		private $session;
		private $actionName;
		private $contextPath;
		private $extension = "";

		/**
		 * Class constructor
		 *
		 * @param string $contextPath
		 */
		function __construct($contextPath) {
			$this->contextPath = $contextPath;
			$this->request = new Request();
			$this->session = new DefaultSession();

			$this->extension = AlfaConfiguration::getInstance()->getString("webapp/controller/action-extension", "");
			if (StringUtils::isNotBlank($this->extension)) {
				$this->extension = ".$this->extension";
			}

			$this->parseActionFromRequest();
		}

		/**
		 * Extracts the action name and parameters from the request URI
		 * @access public
		 */
		public function parseActionFromRequest() {
			$this->actionName = $this->getRequest()->getString('_ac', '');
			if (StringUtils::isNotBlank($this->actionName)) {
				if (ereg ("([a-zA-Z0-9/]+)($this->extension){1}((.*)+)?", $this->actionName, $regs)) {
					$this->actionName = $regs[1];

					// put the params in request
					if (StringUtils::isNotBlank($regs[3])) {
						$params = split("/",$regs[3]);
						if (sizeof($params)%2 == 1) {
							$params[] = "";
						}
						$len = sizeof($params) - 1;
						for ($i = 1; $i < $len; $i+=2) {
							$this->request->setString($params[$i], $params[$i + 1]);
						}
					}
				}
			}
		}

		/**
		 * Returns the request object
		 * @access public
		 * @return Request
		 */
		public function getRequest() {
			return $this->request;
		}

		/**
		 * Returns the session object
		 * @access public
		 * @return Session
		 */
		public function getSession() {
			return $this->session;
		}

		/**
		 * Gets the list of request attributes
		 * @access public
		 * @return array The attribute list
		 */
		public function getAttributes() {
			return $this->request->getAttributes();
		}

		/**
		 * Gets the current request action
		 * @access public
		 * @return string The action
		 */
		public function getAction() {
			return $this->actionName;
		}

		/**
		 * Redirect to another URL. If the given path starts with '/', the path is
		 * assumed to be absolute under this application.
		 * @access public
		 * @param string The path to redirect to
		 */
		public function redirect($path) {
			$newPath = self::normalizePath($path);
			header('Location: ' . $newPath);
			return null;
		}

		/**
		 * Normalize a internal application path
		 * @access public
		 * @param string a relative path
		 * @return string relative path to server root
		 */
		public function normalizePath($path) {
			if ($path === "core") {
				return AlfaApplication::getCoreRoot();
			}

			if (!StringUtils::startsWith($this->getContextPath(), $path)) {
				$path = StringUtils::startsWith("/", $path) ? $this->getContextPath() . substr($path, 1) : $path;
			}

			if (!StringUtils::endsWith("/", $path) &&
					!eregi("([a-zA-Z0-9/]+)($this->extension){1}((.*)+)?", $path)) {
				$path = $path . $this->extension;
			}

			return $path;
		}

		/**
		 * This function is used by the decorator to display
		 * absoulte URLs in the page
		 * @access public
		 * @param array List of params
		 * @return string
		 */
		public function composeURL($params) {
			if(!empty($params['action'])) {
				$path = !StringUtils::startsWith("/", $path) ? "/" . $params['action'] : $params['action'];
				return $this->normalizePath($path);
			}
		  	return $this->normalizePath("");
		}

		/**
		 * Returns the application's root path
		 * @access public
		 * @return string
		 */
		public function getContextPath() {
			return AlfaApplication::getAppRoot();
		}

		/**
		 * Gets the user from the session
		 * @access public
		 * @return User
		 */
		public function getUser() {
			return $this->session->get("__remote_user");
		}

		/**
		 * Sets the logged user in the session
		 * @access public
		 * @param User
		 */
		public function setUser($user) {
			return $this->session->set("__remote_user", $user);
		}

		/**
		 * Gets the list of roles from the session
		 * @access public
		 * @return array List of roles
		 */
		public function getRoles() {
			return $this->session->get("__security_roles", array());
		}

		/**
		 * Puts a list of roles in the session
		 * @access public
		 * @param array List of roles
		 */
		public function setRoles($roles) {
			$this->session->set("__security_roles", $roles);
		}

		/**
		 * Returns true if the specified role name is in the list of
		 * roles from the current user session
		 * @access public
		 * @param string
		 * @return boolean
		 */
		public function hasRole($rolename) {
			return in_array($rolename, $this->getRoles());
		}

		/**
		 * Returns true a user is logged in the current session
		 * @access public
		 * @return boolean
		 */
		public function isUserLoggedIn() {
			$user = $this->getUser();
			return isset($user);
		}
	}
}